package com.gzdh.tang.dishrecognition.rule;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzdh.tang.ali.model.OuterExtends;
import com.gzdh.tang.comm.constant.SpringContextUtils;
import com.gzdh.tang.comm.handler.IPayRuleHandler;
import com.gzdh.tang.comm.util.SnowFlake;
import com.gzdh.tang.config.weixin.WXEntity;
import com.gzdh.tang.config.weixin.WXPay;
import com.gzdh.tang.config.weixin.WXPayUtils;
import com.gzdh.tang.dishrecognition.model.PayModelReq;
import com.gzdh.tang.dishrecognition.model.WeekMenuBakModelReq;
import com.gzdh.tang.mobile.service.KlService;
import com.gzdh.tang.modu.entity.*;
import com.gzdh.tang.modu.model.MainpOrderPayModel;
import com.gzdh.tang.modu.service.*;
import com.gzdh.tang.modu.util.DateUtil;
import com.gzdh.tang.warehouse.service.DeviceService;
import com.gzdh.tang.warehouse.service.InStockService;
import lombok.extern.slf4j.Slf4j;


import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class DrCashAndQrRule implements IPayRuleHandler {
    FkService fkService;

    GsService gsService;

    MacMainpSbruanService macMainpSbruanService;

    MacMainpSbruanDinnerService macMainpSbruanDinnerService;

    MacMainpSbruanKlService macMainpSbruanKlService;

    ReserveService reserveService;

    TangDeviceService tangDeviceService;

    DeviceService deviceService;

    InStockService inStockService;

    KlService klService;

    ReserveXfjTempService reserveXfjTempService;

    TangAddrService tangAddrService;

    MacMainpOrderService macMainpOrderService;


    public DrCashAndQrRule() {
        fkService = (FkService) SpringContextUtils.getBean("fkServiceImpl");
        gsService = (GsService) SpringContextUtils.getBean("gsService");
        macMainpSbruanService = (MacMainpSbruanService) SpringContextUtils.getBean("macMainpSbruanService");
        macMainpSbruanDinnerService = (MacMainpSbruanDinnerService) SpringContextUtils.getBean("macMainpSbruanDinnerService");
        macMainpSbruanKlService = (MacMainpSbruanKlService) SpringContextUtils.getBean("macMainpSbruanKlService");
        reserveService = (ReserveService) SpringContextUtils.getBean("reserveService");
        tangDeviceService = (TangDeviceService) SpringContextUtils.getBean("tangDeviceServiceImpl");
        deviceService = (DeviceService) SpringContextUtils.getBean("deviceServiceImpl");
        inStockService = (InStockService) SpringContextUtils.getBean("inStockService");
        klService = (KlService) SpringContextUtils.getBean("klService");
        reserveXfjTempService = (ReserveXfjTempService) SpringContextUtils.getBean("reserveServiceXfjTemp");
        tangAddrService = (TangAddrService) SpringContextUtils.getBean("tangAddrServiceImpl");
        macMainpOrderService = (MacMainpOrderService) SpringContextUtils.getBean("macMainpOrderService");
    }

    @Override
    public JSONObject toCardPay(JSONObject params) throws RuntimeException {
        return toQrPay(params);
    }

    /**
     * 现金支付：
     * 获取cardno，并直接写入reserve表中
     * 返回支付成功消息
     */
    @Override
    public JSONObject toCashPay(JSONObject params) throws RuntimeException {
        PayModelReq payModelReq = params.toJavaObject(PayModelReq.class);
        MacMainpSbruan macMainpSbruan = macMainpSbruanService
                .getOne(new QueryWrapper<MacMainpSbruan>().lambda().eq(MacMainpSbruan::getMac, payModelReq.getDeviceId()));
        String orders = "XJZF" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        Fk fk = null;
        String posnum = params.getString("userId");
        if (macMainpSbruan.getUsePostType() == 0) {
            posnum = macMainpSbruan.getPos();
        }
        macMainpSbruan.setPos(posnum);
        fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, macMainpSbruan.getCardno()));
        if (fk == null) {
            throw new RuntimeException("cardno尚未设置");
        }
        Date date = payModelReq.getCzrq() != null ? payModelReq.getCzrq() : new Date();
        int i = 0;
        String dinner = getDinner(macMainpSbruan).trim();
        for (WeekMenuBakModelReq goo : payModelReq.getProductCartModelList()) {
            i++;
            if ("xjc".equals(goo.getBm())) {
                goo.setBm(macMainpSbruan.getCode());
                goo.setZl(macMainpSbruan.getZl());
            }
            Reserve reserve = new Reserve();
            reserve.setCardno(fk.getCardno());
            reserve.setZl(goo.getZl());
            reserve.setBqh(macMainpSbruan.getBqh());
            reserve.setKsh(macMainpSbruan.getKsh());
            reserve.setBed("0");
            reserve.setPosnum(macMainpSbruan.getPos());
            reserve.setDinner(dinner);
            reserve.setCode(goo.getBm());
            reserve.setSl(goo.getNumber());
            reserve.setJe(new BigDecimal(goo.getNumber()).multiply(new BigDecimal(goo.getPrice())).toPlainString());
            reserve.setYe("0");
            reserve.setKl(fk.getKl());
            reserve.setSc("2");
            reserve.setLsh2(orders);
            reserve.setCzrq(new Date(date.getTime() + (i * 10L)));
            reserve.setDcrq(new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date()));
            reserve.setHname(goo.getName());
            reserve.setSddz(payModelReq.getDeviceId());
            reserve.setCs(0);
            reserve.setKehu(fk.getName());
            reserve.setZfserialnumber(orders);
            reserve.setStatus("1");
            reserve.setAddr(macMainpSbruan.getAddr());
            reserveService.save(reserve);
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("fk", fk);
        jsonObject.put("success", true);
        jsonObject.put("msg", "支付成功");
        jsonObject.put("orders", orders);
        jsonObject.put("posnum", posnum);
        jsonObject.put("userName", fk.getName());
        jsonObject.put("amount", payModelReq.getAmountPriceSum().toPlainString());
        List<OuterExtends> outerExtendsList = new ArrayList<>();
        outerExtendsList.add(addOutOuterExtends("姓名", fk.getName()));
        outerExtendsList.add(addOutOuterExtends("消费金额", payModelReq.getAmountPriceSum().toPlainString()));
        outerExtendsList.add(addOutOuterExtends("卡余额", fk.getKye()));
        outerExtendsList.add(addOutOuterExtends("补贴余额", fk.getBtye()));
        jsonObject.put("outerExtends", outerExtendsList);
        return jsonObject;
    }

    private String getDinner(MacMainpSbruan macMainpSbruan) throws RuntimeException {
        try {
            String hourMin = new SimpleDateFormat("HH:mm").format(new Date());
            List<MacMainpSbruanDinner> macMainpSbruanDinnerList = macMainpSbruanDinnerService
                    .list(new QueryWrapper<MacMainpSbruanDinner>().lambda().eq(MacMainpSbruanDinner::getDeviceId, macMainpSbruan.getId()));
            for (MacMainpSbruanDinner goo : macMainpSbruanDinnerList) {
                if (DateUtil.hourMinuteBetween(hourMin, goo.getStartTime(), goo.getEndTime())) {
                    return goo.getDinner();
                }
            }
            throw new Exception("未找到该餐次");
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }


    }

    /**
     * 先将记录保存到临时表中，并且发起支付，返回支付结果，
     * 如果需要密码返回特定代码，等待查单
     */
    @Override
    public JSONObject toQrPay(JSONObject params) throws RuntimeException {
        PayModelReq payModelReq = params.toJavaObject(PayModelReq.class);
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda().eq(MacMainpSbruan::getMac, payModelReq.getDeviceId()));
        String orders = "WXZF" + new SimpleDateFormat("HHmmss").format(new Date()) + SnowFlake.nextId() + String.format("%04d", macMainpSbruan.getAddr());
        Fk fk = null;

        fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, macMainpSbruan.getCardno()));
        if (fk == null) {
            throw new RuntimeException("cardno尚未设置");
        }
        String dinner = getDinner(macMainpSbruan).trim();
        for (WeekMenuBakModelReq goo : payModelReq.getProductCartModelList()) {
            goo.setDinner(dinner);
        }
        String posnum = params.getString("userId");
        if (macMainpSbruan.getUsePostType() == 0) {
            posnum = macMainpSbruan.getPos();
        }
        macMainpSbruan.setPos(posnum);
        MainpOrderPayModel mainpOrderPayModel = macMainpOrderService.saveOrderTemp(payModelReq, orders, macMainpSbruan, fk);

        JSONObject jsonObject = new JSONObject();
        try {
            WXEntity wxEntity = new WXEntity();
            WXPay wxPay = new WXPay(wxEntity);
            Map<String, String> reqMap = new HashMap<>();
            reqMap.put("out_trade_no", orders);
            if (WXPayUtils.getSubmchMode() == 1) {
                reqMap.put("sub_mch_id", WXPayUtils.getSubMchId());
            }
            reqMap.put("body", "tangshi");
            reqMap.put("spbill_create_ip", "8.8.8.8");
            reqMap.put("total_fee", mainpOrderPayModel.getAmountPrice().multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString());
            reqMap.put("auth_code", payModelReq.getAuth());
            Map<String, String> resMap = wxPay.microPay(reqMap);
            System.out.println(resMap.toString());
            log.info(resMap.toString());
            if ("SUCCESS".equals(resMap.get("result_code")) && "SUCCESS".equals(resMap.get("return_code"))) {
                jsonObject.put("wxPayStatus", "SUCCESS");
                macMainpOrderService.judOrder(orders);

            } else if ("SUCCESS".equals(resMap.get("trade_state")) || "ACCEPT".equals(resMap.get("trade_state"))) {
                //支付成功订单
                jsonObject.put("wxPayStatus", "SUCCESS");
                macMainpOrderService.judOrder(orders);

            } else if ("USERPAYING".equals(resMap.get("trade_state")) || "USERPAYING".equals(resMap.get("err_code"))) {
                jsonObject.put("wxPayStatus", "USERPAYING");
            } else {
                jsonObject.put("wxPayStatus", "ERROR");
                throw new RuntimeException("支付失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("支付失败");
        }
        jsonObject.put("fk", fk);
        jsonObject.put("userName", fk.getName());
        jsonObject.put("orders", orders);
        jsonObject.put("posnum", posnum);
        jsonObject.put("amount", payModelReq.getAmountPriceSum().toPlainString());
        List<OuterExtends> outerExtendsList = new ArrayList<>();
        outerExtendsList.add(addOutOuterExtends("姓名", fk.getName()));
        outerExtendsList.add(addOutOuterExtends("消费金额", payModelReq.getAmountPriceSum().toPlainString()));
        outerExtendsList.add(addOutOuterExtends("卡余额", fk.getKye()));
        outerExtendsList.add(addOutOuterExtends("补贴余额", fk.getBtye()));
        jsonObject.put("outerExtends", outerExtendsList);
        return jsonObject;
    }

    @Override
    public JSONObject toFacePay(JSONObject params) throws RuntimeException {
        throw new RuntimeException("支付失败");
    }

    private OuterExtends addOutOuterExtends(String name, String value) {
        OuterExtends outerExtends = new OuterExtends();
        outerExtends.setTitle(name);
        outerExtends.addDetail(name, value);
        return outerExtends;
    }
}
